/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

/**
 *
 * 1 实例化 (Instantiation): Spring 容器通过反射或 CGLIB 来创建 bean 的实例。
 * 2 属性填充 (Populate Properties): 在实例化之后，Spring 会将配置的依赖注入到这个新创建的 bean 实例中。这包括设置属性值、依赖查找等操作。
 * 3 postProcessBeforeInitialization 方法调用: 如果有实现 BeanPostProcessor 接口的类，Spring 将在这个阶段调用 postProcessBeforeInitialization 方法。这是在任何初始化回调之前，但在属性填充完成之后发生的。
 * 4 初始化回调方法:
 * 	 	1）@PostConstruct（构造函数后置处理注解） 注解的方法调用: 如果存在标有 @PostConstruct 注解的方法，它将在此时被调用。
 * 	    2）InitializingBean.afterPropertiesSet 方法调用: 如果该 bean 实现了 InitializingBean 接口，那么其 afterPropertiesSet 方法会被调用。
 * 5 自定义初始化方法: 如果指定了自定义的初始化方法（例如通过 XML 配置中的 init-method 属性或注解配置中的 @Bean(initMethod="methodName")），那么这个方法也会在此时被调用。
 * 6 postProcessAfterInitialization 方法调用: 最后，如果有实现 BeanPostProcessor 接口的类，Spring 将调用 postProcessAfterInitialization 方法。这是在所有初始化工作完成后进行的最后处理步骤，常用于代理对象的创建等。
 *
 *  * 1、MyBean: Instance created (Instantiation) (实例创建)
 *  * 2、MyBean: Name set to exampleName	(命名)
 *  * 3、MyBean: postProcessBeforeInitialization method called (初始化前调用方法)
 *  * 4、MyBean: PostConstruct method called	(初始化回调方法1)
 *  * 5、MyBean: afterPropertiesSet method called  (初始化回调方法2)
 *  * 6、MyBean: Custom init method called 	(自定义初始化方法)
 *  * 7、MyBean: postProcessAfterInitialization method called (初始化后调用方法)
 *
 * 1 MyBean 实例创建。
 * 2 属性填充（如设置名称 exampleName）。
 * 3 postProcessBeforeInitialization 方法调用。
 * 4 @PostConstruct 方法调用。
 * 5 afterPropertiesSet 方法调用（如果实现了 InitializingBean 接口）。
 * 6 自定义初始化方法调用（如果有指定）。
 * 7 postProcessAfterInitialization 方法调用。
 *
 * <br>
 * Factory hook that allows for custom modification of new bean instances &mdash;
 * for example, checking for marker interfaces or wrapping beans with proxies.
 *<br> 工厂钩子，允许对新的 bean 实例进行自定义修改 &mdash; 例如，检查标记接口或使用代理包装 bean 。
 * <p>Typically, post-processors that populate beans via marker interfaces
 * or the like will implement {@link #postProcessBeforeInitialization},
 * while post-processors that wrap beans with proxies will normally
 * implement {@link #postProcessAfterInitialization}.
 * <br> 典型的，通过标记接口或类似的方法填充 bean 的后处理器将实现 {@link #postProcessBeforeInitialization} 方法，
 * 而使用代理包装 bean 的后处理器将实现 {@link #postProcessAfterInitialization} 方法。
 *
 * <h3>Registration</h3>
 * <h3>注册</h3>
 * <p>An {@code ApplicationContext} can autodetect {@code BeanPostProcessor} beans
 * in its bean definitions and apply those post-processors to any beans subsequently
 * created. A plain {@code BeanFactory} allows for programmatic registration of
 * post-processors, applying them to all beans created through the bean factory.
 * <br> 一个 ApplicationContext 可以 在bean定义中自动检测自动检测 BeanPostProcessor beans ，并将这些后处理器应用于任何随后创建的bean。
 * 一个普通的 BeanFactory 允许以编程方式注册后处理器，并将它们应用于通过 bean 工厂创建的任何bean。
 *
 * <h3>Ordering</h3>
 * <h3>排序</h3>
 * <p>{@code BeanPostProcessor} beans that are autodetected in an
 * {@code ApplicationContext} will be ordered according to
 * {@link org.springframework.core.PriorityOrdered} and
 * {@link org.springframework.core.Ordered} semantics. In contrast,
 * {@code BeanPostProcessor} beans that are registered programmatically with a
 * {@code BeanFactory} will be applied in the order of registration; any ordering
 * semantics expressed through implementing the
 * {@code PriorityOrdered} or {@code Ordered} interface will be ignored for
 * programmatically registered post-processors. Furthermore, the
 * {@link org.springframework.core.annotation.Order @Order} annotation is not
 * taken into account for {@code BeanPostProcessor} beans.
 *
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 10.10.2003
 * @see InstantiationAwareBeanPostProcessor
 * @see DestructionAwareBeanPostProcessor
 * @see ConfigurableBeanFactory#addBeanPostProcessor
 * @see BeanFactoryPostProcessor
 */
public interface BeanPostProcessor {

	/**
	 * <p>
	 *     在任何初始化回调（如 @PostConstruct 或 InitializingBean.afterPropertiesSet()）之前调用。
	 * </p>
	 *
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other {@code BeanPostProcessor} callbacks.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
